import hashlib
import mimetypes
import random
import string
import uuid
import datetime
from datetime import datetime as dt
import jwt
from django.contrib.sites import requests
from django.db.models import Q
from django.forms import ModelForm
from django.http import JsonResponse, HttpResponse, FileResponse
from .models import User
from django.views import View
import json
from django.conf import settings
from .serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response  # 我还是用了drf这里，因为我看这样的话写POST的时候更简单一些
from django.utils import timezone
import time
from urllib.parse import parse_qs
import requests
from openpyxl import Workbook
import pandas as pd
import pytz
from bs4 import BeautifulSoup  # pip install beautifulsoup4
import requests
import datetime
import math
import re


def generate_random_string(length=10):
    """生成指定长度的随机字符串，包含字母和数字"""
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))


def create_manager_token(man_id, timeout=1800):
    # 自定义token 这里过期时间设置为分钟，真正项目设置三天吧，因为我看需要刷新token的是极少数安全性网站，咱应该也没必要
    # 陈：嗯好
    expire_time = timezone.now() + timedelta(minutes=timeout)
    payload = {
        'exp': expire_time,
        'id': man_id
    }
    result = jwt.encode(payload=payload, key=settings.SECRET_KEY, algorithm='HS256')
    return result


def create_user_token(openid, user_id, timeout=4320):  # 自定义token
    expire_time = timezone.now() + timedelta(minutes=timeout)
    payload = {
        'exp': expire_time,
        'openid': openid,
        'id': user_id
    }
    result = jwt.encode(payload=payload, key=settings.SECRET_KEY, algorithm='HS256')
    return result


def verify_token(token):  # 验证token函数
    result = {'status': False, 'data': None, 'error': None}
    try:
        verified_payload = jwt.decode(token, key=settings.SECRET_KEY, verify=False,
                                      algorithms=['HS256'])  # 这里verify需要改，但是调试阶段不需要
        result['status'] = True
        result['data'] = verified_payload
    except jwt.DecodeError:
        result['error'] = 'token认证失败'
    except jwt.InvalidTokenError:
        result['error'] = 'token失效或携带关键字错误'
    return result


def is_login_manager(token):  # 验证管理员登录情况的函数
    if not token:
        return {'code': 419, 'message': '未登录'}  # 处理未携带token的情况
    result = verify_token(token)
    if result.get('status'):
        temp = result['data']
        manager_id = temp['id']
        try:
            obj = Manager.objects.filter(id=manager_id).first()
        except Exception as e:
            return Response({'code': 500, "message": '用户不存在，token错误', "error": str(e)})
        if obj:
            return {'code': 200, 'message': '已登录'}
        else:
            return {'code': 404, 'message': "目标不存在"}
    else:
        return {'code': 400, "message": result.get('error')}


def is_login_supermanager(token):  # 验证超级管理员登录情况的函数
    if not token:
        return {'code': 419, 'message': '未登录'}  # 处理未携带token的情况
    result = verify_token(token)
    if result.get('status'):
        temp = result['data']
        manager_id = temp['id']
        if 0 < manager_id < 4:  # 我不打算新建一个类了，就让manager里面id值1-3的为超级管理员
            return {'code': 200, 'message': '超级管理员已登录'}
        else:
            return {'code': 404, 'message': "您不是超级管理员"}
    else:
        return {'code': 400, "message": result.get('error')}


def is_login_user(token):
    if not token:
        return {'code': 419, 'message': '未携带token'}  # 处理未携带token的情况
    try:
        result = verify_token(token)
    except Exception as e:
        return Response({'code': 500, "message": 'token错误', "error": str(e)})
    if result.get('status'):
        temp = result['data']
        user_id = temp['id']
        try:
            obj = User.objects.filter(id=user_id).first()
        except Exception as e:
            return Response({'code': 500, "message": '用户不存在，token错误', "error": str(e)})
        if obj:
            return {'code': 200, 'message': '已登录'}
        else:
            return {'code': 404, 'message': "用户不存在"}
    else:
        return {'code': 400, "message": result.get('error')}


class LoginDemo(APIView):
    def post(self,request):
        data = request.body.decode('utf-8')
        json_data = json.loads(data)
        user_openid = json_data.get('user_openid')
        obj = User.objects.filter(user_openid=user_openid).first()
        print(obj)
        user_key = {
            'openid': user_openid,
            'id': obj.id,
        }
        if not obj:
            return Response({'code': 401, 'message': '登录失败'})
        else:
            token = create_user_token(obj.user_openid, obj.id)
            return Response({'code': 200, 'token': token, 'data': user_key, 'message': '登录成功'})


class wx_login(APIView):
    def post(self, request):  # 参考下其他的，这里是要加self的
        # 获取微信登录凭证 code
        print(request)
        code = request.data.get('code')
        print(code)

        # 向微信服务器发送请求，获取用户的 openid 和 session_key
        params = {
            # 'appid': settings.AppId,
            'appid': 'wxa78169eeb3e130bc',
            # 'secret': settings.AppSecret,
            'secret': 'eb7112918a20263bf6517fffb92c9c4a',
            'js_code': code,
            'grant_type': 'authorization_code'
        }


        response = requests.get('https://api.weixin.qq.com/sns/jscode2session', params=params)
        data = response.json()
        print(data)

        # 处理获取到的用户信息
        if 'openid' in data:
            openid = data['openid']
            session_key = data['session_key']
            try:
                obj = User.objects.get(user_openid=openid)  # 是否存在该用户
            except Exception as e:
                obj = User.objects.create(  # 这样下面才能用obj.调用
                    user_openid=openid,
                )
                user_key = {
                    'openid': obj.user_openid,
                    'id': obj.id,
                    'session_key': session_key,
                    'token': create_user_token(obj.user_openid, obj.id)  # 这里也得要token的吧
                }
                return Response({'code': 200, 'data': user_key, 'message': '用户已创建'})
            else:
                user_key = {
                    'openid': obj.user_openid,
                    'id': obj.id,
                    'session_key': session_key,
                    'token': create_user_token(obj.user_openid, obj.id)
                }
                return Response({'code': 200, 'data': user_key, 'message': '获取成功！'})
        else:
            # 处理错误情况
            return Response({'error': 'Failed to get openid and session_key'})


class SuggForm(ModelForm):  # 比较简洁的表单写法
    class Meta:
        model = Suggestion
        fields = ['sugg_name', 'sugg_text', 'sugg_user_tele', 'sugg_site',
                  'sugg_sub_id', 'sugg_title', 'sugg_treat']  # sugg_sub_id得填提交建议的用户的主键


class CompForm(ModelForm):  # 比较简洁的表单写法
    class Meta:
        model = Complaint
        fields = ['comp_name', 'comp_text', 'comp_user_tele', 'comp_site',
                  'comp_sub_id', 'comp_title', 'comp_treat']


class UserForm(ModelForm):
    class Meta:
        model = User
        fields = ['id', 'user_openid', 'user_nick', 'user_tele', 'user_info', 'user_image', 'user_address']


def handle_uploaded_image(image_file):   # 处理文件，赋给新的路径
    # 构造要保存图片的路径
    timestamp = str(int(timezone.now().timestamp() * 1000)) + generate_random_string(8)
    # 获取上传文件的扩展名
    file_extension = os.path.splitext(image_file.name)[1]
    # 构建保存图片的路径，并将时间戳和原始扩展名拼接在一起作为文件名
    save_path = os.path.join(settings.MEDIA_ROOT, 'files', timestamp + file_extension)
    # 确保目录存在
    save_dir = os.path.dirname(save_path)  # 提取父目录路径
    if not os.path.exists(save_dir):
        try:
            os.makedirs(save_dir)  # 创建目录
            print(f"创建目录: {save_dir}")
        except OSError as e:
            print(f"创建目录时出错: {e}")

    # 检查是否有写权限
    if not os.access(save_dir, os.W_OK):
        print(f"没有写权限: {save_dir}")
    # 打开文件并保存
    try:
        with open(save_path, 'wb+') as destination:
            for chunk in image_file.chunks():
                destination.write(chunk)
    except Exception as e:
        print(f"保存文件时出错: {e}")
        return None

    return save_path


class ManagerLogin(APIView):  # Manager视图完成，所有功能验证，这里更改密码需要输入确认密码，不允许更改用户名，第一次默认密码为123456
    def post(self, request):
        try:
            data = request.body.decode('utf-8')
            json_data = json.loads(data)
            manager_account = json_data.get('manager_account')
            manager_code = json_data.get('manager_code')
        except Exception as e:
            return Response({'code': 500, "message": '管理登录数据出错', "error": str(e)})

        encry = hashlib.md5()  # 实例化md5
        encry.update(manager_code.encode())  # 字符串字节加密
        manager_pwd = encry.hexdigest()
        try:
            obj = Manager.objects.filter(manager_account=manager_account, manager_code=manager_pwd).first()
        except Exception as e:
            return Response({'code': 500, "message": '管理数据未获取', "error": str(e)})
        if not obj:
            return Response({'code': 401, 'message': '登录失败'})
        else:
            token = create_manager_token(obj.id)
            return Response({'code': 200, 'token': token, 'message': '登录成功'})


class ManagerDetail(APIView):
    def get(self, request):
        # 应该不用再传主键了，依据token里的信息给具体信息就行了
        # 我写了个判断登录状态的函数，这样就不用一遍一遍写大段的代码了
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            manager_id = aa['id']
            try:
                obj = Manager.objects.filter(id=manager_id).first()
                ser = ManagerSerializer(instance=obj, many=False)
            except Exception as e:
                return Response({'code': 500, "message": '管理信息数据获取出错', "error": str(e)})
            return Response({"code": 200, "data": ser.data})
        else:
            return Response(login_status)

    def put(self, request):
        # 同样不用传入主键了
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            manager_id = aa['id']
            data = request.body.decode('utf-8')
            try:
                json_data = json.loads(data)
                manager_name = json_data.get('manager_name')
                manager_tele = json_data.get('manager_tele')
                manager_account = json_data.get('manager_account')
                manager_code = json_data.get('manager_code')
                manager_recode = json_data.get('manager_recode')
            except Exception as e:
                return Response({'code': 500, "message": '管理信息格式错误', "error": str(e)})
            # 这里改了下，要不然我只填了姓名的话，最后数据库里电话就为null了（只能让管理员一次就该一个字段了）
            if manager_name and manager_tele and manager_account:
                try:
                    Manager.objects.filter(id=manager_id).update(manager_name=manager_name, manager_tele=manager_tele, manager_account=manager_account)
                except Exception as e:
                    return Response({'code': 500, "message": '管理登录数据出错', "error": str(e)})
                return Response({'code': 200, 'message': '修改成功'})
            elif manager_code or manager_recode:
                if manager_code == manager_recode:
                    encry = hashlib.md5()  # 实例化md5
                    encry.update(manager_code.encode())  # 字符串字节加密
                    manager_pwd = encry.hexdigest()
                    try:
                        Manager.objects.filter(id=manager_id).update(manager_code=manager_pwd)
                    except Exception as e:
                        return Response({'code': 500, "message": '管理密码保存出错', "error": str(e)})
                    return Response({'code': 200, 'message': '修改密码成功'})
                else:
                    return Response({'code': 400, 'message': '两次密码不一致'})
            else:
                return Response({'code': 400, 'message': '无信息'})
        else:
            return Response(login_status)


class ManagerAdd(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_supermanager(token)
        if login_status['code'] == 200:
            try:
                data = request.body.decode('utf-8')
                json_data = json.loads(data)
                manager_account = json_data.get('manager_account')
                manager_code = json_data.get('manager_code')
            except Exception as e:
                return Response({'code': 500, "message": '添加管理数据格式错误', "error": str(e)})

            encry = hashlib.md5()
            encry.update(manager_code.encode())  # 字符串字节加密
            manager_pwd = encry.hexdigest()
            if manager_account and manager_pwd:
                try:
                    Manager.objects.create(manager_account=manager_account, manager_code=manager_pwd)
                except Exception as e:
                    return Response({'code': 500, "message": '管理创建出错', "error": str(e)})
                return Response({'code': 200, "message": '增加管理员成功'})
            else:
                return Response({'code': 400, "message": '增加管理员失败'})
        else:
            return Response(login_status)


class SuggestionAll(APIView):
    def get(self, request):  # 这里的get为管理员查询
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                params = Suggestion.objects.filter(sugg_status=False)
                if params.exists():
                    ser = SuggestionSerializer_list(instance=params, many=True)
                    return Response({'code': 200, 'data': ser.data, 'message': '获取表单简介成功'})
                else:
                    return Response({'code': 404, 'message': "未找到未处理表单"})
            except Exception as e:
                return Response({'code': 500, 'message': f'未知错误: {str(e)}'})
        else:
            return Response(login_status)


class SuggestionTreat(APIView):  # 第二次回传，要通过两次筛选，筛选未处理且标志位为1的表单，要注意此时序列化器
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            params1 = Suggestion.objects.filter(sugg_status=True).all()
            if params1:
                params2 = Suggestion.objects.filter(sugg_treat=1).filter(sugg_status=True).all()
                if params2:
                    try:
                        ser = SuggestionSerializer_list(instance=params2, many=True)
                        return Response({'code': 200, 'data': ser.data, "message": '获取待回访表单成功'})
                    except Exception as e:
                        return Response({'code': 404, "message": '返回失败', "error": str(e)})
                else:
                    return Response({'code': 404, 'message': "未找到回访未处理表单"})
            else:
                return Response({'code': 404, 'message': "未找到表单"})
        else:
            return Response(login_status)


class SuggestionTreatWhich(APIView):
    def put(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                obj = Suggestion.objects.get(pk=pk)
            except Exception as e:
                return Response({'code': 404, "message": '未找到相应回访表', "error": str(e)})  # 这个类型报错很好用，可以直接返回错误信息，便于调试
            try:
                ser = SuggestionTreatSerializer(instance=obj, data=request.data)
            except Exception as e:
                return Response({'code': 400, "message": '未完成更新', "error": str(e)})
            if ser.is_valid():
                ser.save()
                return Response({'code': 200, 'data': ser.data, 'message': '回访成功'})
            else:
                return Response({'code': 400, 'massage': ser.errors})
        else:
            return Response(login_status)


class SuggestionListDetail(APIView):
    def get(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            params = Suggestion.objects.filter(pk=pk).all()
            if params:
                try:
                    ser = SuggestionSerializer(instance=params, many=True)
                    return Response({'code': 200, 'data': ser.data, "message": '获取某一表单成功'})
                except Exception as e:
                    return Response({'code': 404, "message": '返回失败', "error": str(e)})
            else:
                return Response({'code': 404, 'message': '无未处理的投诉'})
        else:
            return Response(login_status)

    def put(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)

        if login_status['code'] != 200:
            return Response(login_status)

        try:
            obj = Suggestion.objects.get(pk=pk)
        except Exception as e:
            return Response({'code': 404, "message": '未找到相应投诉表', "error": str(e)})
        try:
            ser = SuggestionFeedbackSerializer(instance=obj, data=request.data)
        except Exception as e:
            return Response({'code': 400, "message": '投诉表序列化出错', "error": str(e)})
        if ser.is_valid():
            try:
                ser.save()
                return Response({'code': 200, 'data': ser.data, 'message': '修改投诉表成功'})
            except Exception as e:
                return Response({'code': 400, "message": '投诉表保存出错', "error": str(e)})
        else:
            return Response({'code': 400, 'message': ser.errors})


class SuggestionUser(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            form = SuggForm(request.POST)
            images = request.FILES.getlist('sugg_media')
            if form.is_valid():
                try:
                    # 保存表单数据
                    suggestion_instance = form.save()
                except Exception as e:
                    return Response({'code': 500, 'message': '表单保存失败', 'error': str(e)})

                if images:
                    try:
                        for image_file in images:
                            # 直接将文件对象传递给 ImageField，文件名由 upload_to 函数处理
                            suggestion_media = SuggestionMedia(sugg_media=image_file, sugg_list=suggestion_instance)
                            suggestion_media.save()
                    except Exception as e:
                        return Response({'code': 500, 'message': '图片保存失败', 'error': str(e)})

                    return Response({'code': 200, 'message': '提交图片和表单成功'})
                else:
                    return Response({'code': 200, 'data': form.data, 'message': '提交成功'})
            else:
                return Response({'code': 400, 'message': form.errors})
        else:
            return Response(login_status)


class SuggestionWhich(APIView):
    def get(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)   # 用户使用某个表单查询
        if login_status['code'] == 200:
            try:
                obj = Suggestion.objects.filter(pk=pk).prefetch_related('suggestionmedia_set').all()
                ser = SuggestionSerializer(instance=obj, many=True, context={'request': request})
            except Exception as e:
                return Response({'code': 500, "message": '用户具体表单获取数据出错', "error": str(e)})
            return Response({'code': 200, 'data': ser.data, 'message': '获取列表成功'})
        else:
            return Response(login_status)

    def put(self, request,pk):  # 用户进行评价的函数
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            try:
                data = json.loads(request.body)
                feedback = data.get('sugg_feedback', None)
            except Exception as e:
                return Response({'code': 500, "message": '提交修改数据格式出错', "error": str(e)})
            if feedback is not None:
                try:
                    obj = Suggestion.objects.get(pk=pk)
                    obj.sugg_feedback = feedback
                    obj.save()
                except Exception as e:
                    return Response({'code': 500, "message": '用户反馈数据保存失败', "error": str(e)})
                return Response({'code': 200, 'data': feedback, 'message':'评价成功！'})
            else:
                return Response({'code': 400, 'message': '评价错误'})
        else:
            return Response(login_status)


class SuggestionUserDetail(APIView):    # 查询本人提交的所有建议
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            try:
                result = verify_token(token)
                aa = result['data']
                user_id = aa['id']
                obj = Suggestion.objects.filter(sugg_sub_id=user_id).prefetch_related('suggestionmedia_set').all()
            except Exception as e:
                return Response({'code': 500, "message": '用户建议表数据获取出错', "error": str(e)})
            if obj:
                ser = SuggestionSerializer(instance=obj, many=True, context={'request': request})
                return Response({'code': 200, 'data': ser.data, 'message': '查询到用户的所有建议'})
            else:
                return Response({'code': 404, 'message': '该用户未提交任何建议'})
        else:
            return Response(login_status)


class ComplaintAll(APIView):  # 第一次回传，获取的只是未处理的表单，要注意这时候的序列化器
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                params = Complaint.objects.filter(comp_status=False)
                if params.exists():
                    ser = ComplaintSerializer_list(instance=params, many=True)
                    return Response({'code': 200, 'data': ser.data, 'message': '获取表单简介成功'})
                else:
                    return Response({'code': 404, 'message': "未找到未处理表单"})
            except Exception as e:
                return Response({'code': 500, 'message': f'未知错误: {str(e)}'})
        else:
            return Response(login_status)


class ComplaintTreat(APIView):  # 第二次回传，要通过两次筛选，筛选未处理且标志位为1的表单，要注意此时序列化器
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            params1 = Complaint.objects.filter(comp_status=True).all()
            if params1:
                params2 = Complaint.objects.filter(comp_treat=1).filter(comp_status=True).all()
                if params2:
                    try:
                        ser = ComplaintSerializer_list(instance=params2, many=True)
                        return Response({'code': 200, 'data': ser.data, "message": '获取待回访表单成功'})
                    except Exception as e:
                        return Response({'code': 404, "message": '返回失败', "error": str(e)})
                else:
                    return Response({'code': 404, 'message': "未找到回访未处理表单"})
            else:
                return Response({'code': 404, 'message': "未找到表单"})
        else:
            return Response(login_status)


class ComplaintTreatWhich(APIView):
    def put(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                obj = Complaint.objects.get(pk=pk)
            except Exception as e:
                return Response({'code': 404, "message": '未找到相应回访表', "error": str(e)})  # 这个类型报错很好用，可以直接返回错误信息，便于调试
            ser = ComplaintTreatSerializer(instance=obj, data=request.data)
            if ser.is_valid():
                ser.save()
                return Response({'code': 200, 'data': ser.data, 'message': '回访成功'})
            else:
                return Response({'code': 400, 'massage': ser.errors})
        else:
            return Response(login_status)


class ComplaintListDetail(APIView):
    def get(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            params = Complaint.objects.filter(pk=pk).all()
            if params:
                try:
                    ser = ComplaintSerializer(instance=params, many=True)
                    return Response({'code': 200, 'data': ser.data, "message": '获取某一表单成功'})
                except Exception as e:
                    return Response({'code': 404, "message": '返回失败', "error": str(e)})
            else:
                return Response({'code': 404, 'message': '无未处理的投诉'})
        else:
            return Response(login_status)

    def put(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)

        if login_status['code'] != 200:
            return Response(login_status)

        try:
            obj = Complaint.objects.get(pk=pk)
        except Exception as e:
            return Response({'code': 404, "message": '未找到相应投诉表', "error": str(e)})
        try:
            ser = ComplaintFeedbackSerializer(instance=obj, data=request.data)
        except Exception as e:
            return Response({'code': 400, "message": '投诉表序列化出错', "error": str(e)})
        if ser.is_valid():
            try:
                ser.save()
                return Response({'code': 200, 'data': ser.data, 'message': '修改投诉表成功'})
            except Exception as e:
                return Response({'code': 400, "message": '投诉表保存出错', "error": str(e)})
        else:
            return Response({'code': 400, 'message': ser.errors})


class ComplaintUser(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            form = CompForm(request.POST)
            images = request.FILES.getlist('comp_media')
            if form.is_valid():
                try:
                    # 保存表单数据
                    complaint_instance = form.save()
                except Exception as e:
                    return Response({'code': 500, 'message': '表单保存失败', 'error': str(e)})

                if images:
                    try:
                        for image_file in images:
                            # 直接将文件对象传递给 ImageField，文件名由 upload_to 函数处理
                            complaint_media = ComplaintMedia(comp_media=image_file, comp_list=complaint_instance)
                            complaint_media.save()
                    except Exception as e:
                        return Response({'code': 500, 'message': '图片保存失败', 'error': str(e)})

                    return Response({'code': 200, 'message': '提交图片和表单成功'})
                else:
                    return Response({'code': 200, 'data': form.data, 'message': '提交成功'})
            else:
                return Response({'code': 400, 'message': form.errors})
        else:
            return Response(login_status)


class ComplaintWhich(APIView):
    def get(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)   # 用户使用某个表单查询
        if login_status['code'] == 200:
            try:
                obj = Complaint.objects.filter(pk=pk).prefetch_related('complaintmedia_set').all()
                ser = ComplaintSerializer(instance=obj, many=True, context={'request': request})
            except Exception as e:
                return Response({'code': 500, "message": '用户具体表单获取数据出错', "error": str(e)})
            return Response({'code': 200, 'data': ser.data, 'message': '获取列表成功'})
        else:
            return Response(login_status)

    def put(self, request, pk):  # 用户进行评价的函数
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            try:
                data = json.loads(request.body)
                feedback = data.get('comp_feedback', None)
            except Exception as e:
                return Response({'code': 500, "message": '提交修改数据格式出错', "error": str(e)})
            if feedback is not None:
                try:
                    obj = Complaint.objects.get(pk=pk)
                    obj.comp_feedback = feedback
                    obj.save()
                except Exception as e:
                    return Response({'code': 500, "message": '用户反馈数据保存失败', "error": str(e)})
                return Response({'code': 200, 'data': feedback, 'message': '评价成功！'})
            else:
                return Response({'code': 400, 'message': '评价错误'})
        else:
            return Response(login_status)


class ComplaintUserDetail(APIView):   # 用户获取detail
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            try:
                result = verify_token(token)
                aa = result['data']
                user_id = aa['id']
                obj = Complaint.objects.filter(comp_sub_id=user_id).prefetch_related('complaintmedia_set').all()
            except Exception as e:
                return Response({'code': 500, "message": '用户投诉表数据获取出错', "error": str(e)})
            if obj:  # 改了下，处理了下用户未提交任何投诉表的问题
                ser = ComplaintSerializer(instance=obj, many=True)
                return Response({'code': 200, 'data': ser.data, 'message': '查询到用户的所有投诉'})
            else:
                return Response({'code': 404, 'message': '该用户未提交任何投诉'})
        else:
            return Response(login_status)


class ManagerHistory(APIView):
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            manager_id = aa['id']
            try:
                obj1 = Suggestion.objects.filter(Q(sugg_handle_id=manager_id, sugg_status=True, sugg_treat=0) | Q(sugg_handle_id=manager_id, sugg_treat=2)).prefetch_related('suggestionmedia_set').all()
                ser1 = SuggestionSerializer(instance=obj1, many=True, context={'request': request})
                obj2 = Complaint.objects.filter(Q(comp_handle_id=manager_id, comp_status=True, comp_treat=0) | Q(comp_handle_id=manager_id, comp_treat=2)).prefetch_related('complaintmedia_set').all()
                ser2 = ComplaintSerializer(instance=obj2, many=True, context={'request': request})
            except Exception as e:
                return Response({'code': 500, "message": '获取所有历史记录出错', "error": str(e)})
            return Response({
                'code': 200,
                'data': {
                    'suggestions': ser1.data,
                    'complaints': ser2.data
                },
                'message': '获取历史记录成功'
            })
        else:
            return Response(login_status)


class ComplaintHistory(APIView):
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            manager_id = aa['id']
            try:
                obj2 = Complaint.objects.filter(Q(comp_handle_id=manager_id, comp_status=True, comp_treat=0) | Q(comp_handle_id=manager_id, comp_treat=2)).prefetch_related('complaintmedia_set').all()
                ser2 = ComplaintSerializer_list(instance=obj2, many=True)
            except Exception as e:
                return Response({'code': 500, "message": '获取所有历史记录出错', "error": str(e)})
            return Response({
                'code': 200,
                'data': ser2.data,
                'message': '获取历史记录成功'
            })
        else:
            return Response(login_status)


class ComplaintHistoryWhich(APIView):
    def get(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                obj2 = Complaint.objects.filter(pk=pk).prefetch_related('complaintmedia_set').all()
                ser2 = ComplaintSerializer(instance=obj2, many=True)
            except Exception as e:
                return Response({'code': 500, "message": '获取所有历史记录出错', "error": str(e)})
            return Response({
                'code': 200,
                'data': ser2.data,
                'message': '获取历史记录成功'
            })
        else:
            return Response(login_status)


class SuggestionHistory(APIView):
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            manager_id = aa['id']
            try:
                obj2 = Suggestion.objects.filter(Q(sugg_handle_id=manager_id, sugg_status=True, sugg_treat=0) | Q(sugg_handle_id=manager_id, sugg_treat=2))
                ser2 = SuggestionSerializer_list(instance=obj2, many=True)
            except Exception as e:
                return Response({'code': 500, "message": '获取所有历史记录出错', "error": str(e)})
            return Response({
                'code': 200,
                'data': ser2.data,
                'message': '获取历史记录成功'
            })
        else:
            return Response(login_status)


class SuggestionHistoryWhich(APIView):
    def get(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                obj2 = Suggestion.objects.filter(pk=pk).prefetch_related('suggestionmedia_set').all()
                ser2 = SuggestionSerializer(instance=obj2, many=True)
            except Exception as e:
                return Response({'code': 500, "message": '获取所有历史记录出错', "error": str(e)})
            return Response({
                'code': 200,
                'data': ser2.data,
                'message': '获取历史记录成功'
            })
        else:
            return Response(login_status)


class UserDetailAll(APIView):
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            user_id = aa['id']
            try:
                obj1 = Suggestion.objects.filter(sugg_sub_id=user_id, sugg_status=True).prefetch_related('suggestionmedia_set').all()
                ser1 = SuggestionSerializerUserAll(instance=obj1, many=True, context={'request': request})
                obj2 = Complaint.objects.filter(comp_sub_id=user_id, comp_status=True).prefetch_related('complaintmedia_set').all()
                ser2 = ComplaintSerializerUserAll(instance=obj2, many=True, context={'request': request})
            except Exception as e:
                return Response({'code': 500, "message": '获取用户所有表单出错', "error": str(e)})
            return Response({
                'code': 200,
                'data': ser1.data + ser2.data,
                'message': '获取用户所有表单成功'
            })
        else:
            return Response(login_status)


class UserFreq(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            user_id = aa['id']
            try:
                freqs = User.objects.filter(id=user_id).first()
                freq = freqs.user_freq + 1
                User.objects.filter(id=user_id).update(user_freq=freq)
            except Exception as e:
                return Response({'code': 500, "message": '用户修改访问量出错', "error": str(e)})
            return Response({'code': 200, 'message': '修改访问次数'})
        else:
            return Response(login_status)


class UserView(APIView):  # 因为先创建用户，所以这里应该是修改
    def put(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            user_id = aa['id']
            try:
                json_data = request.data
                user_image = request.FILES.get('user_image')
                user_info = json_data.get('user_info')
                user_nick = json_data.get('user_nick')
                user_address = json_data.get('user_address')
                user_tele = json_data.get('user_tele')
            except Exception as e:
                return Response({'code': 500, "message": '用户数据出错', "error": str(e)})

            if user_tele:
                try:
                    User.objects.filter(id=user_id).update(user_tele=user_tele)
                except Exception as e:
                    return Response({'code': 500, "message": '用户修改电话出错', "error": str(e)})
                return Response({'code': 200, "message": '修改电话成功'})
            elif user_info:
                try:
                    User.objects.filter(id=user_id).update(user_info=user_info)
                except Exception as e:
                    return Response({'code': 500, "message": '用户修改简介出错', "error": str(e)})
                return Response({'code': 200, "message": '修改简介成功'})
            elif user_nick:
                try:
                    User.objects.filter(id=user_id).update(user_nick=user_nick)
                except Exception as e:
                    return Response({'code': 500, "message": '用户修改昵称出错', "error": str(e)})
                return Response({'code': 200, "message": '修改昵称成功'})
            elif user_address:
                try:
                    user_address = user_address[0]   # 这里要测试
                    User.objects.filter(id=user_id).update(user_address=user_address)
                except Exception as e:
                    return Response({'code': 500, "message": '用户修改地址出错', "error": str(e)})
                return Response({'code': 200, "message": '修改地址成功'})
            elif user_image:
                try:
                    obj = User.objects.get(id=user_id)
                    obj.user_image = user_image
                    obj.save()
                except Exception as e:
                    return Response({'code': 500, "message": '修改图像错误', "error": str(e)})
                return Response({'code': 200, 'message': '修改用户图片成功'})
            else:
                return Response({'code': 200, 'message': '未进行修改'})
        else:
            return Response(login_status)

    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            result = verify_token(token)
            aa = result['data']
            user_id = aa['id']
            users = User.objects.filter(pk=user_id)
            if not users:
                return Response({'code': 200, 'message': '用户不存在'})
            else:
                ser = UserSerializer(instance=users, many=True)
                return Response({'code': 200, 'data': ser.data, 'message': '获取用户成功'})
        else:
            return Response(login_status)


class WarnView(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            ser = WarnSerializer(data=request.data)
            if ser.is_valid():
                try:
                    Warn.objects.create(**ser.validated_data)
                except Exception as e:
                    return Response({'code': 500, "message": '增加温馨提示失败', "error": str(e)})
                return Response({'code': 200, "message": '上传成功'})
            else:
                return Response({'code': 400, "message": '数据格式错误', "data": ser.errors})
        else:
            return Response(login_status)

    def get(self, request):  # 管理员获取
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                warn_obj = Warn.objects.last()
            except Exception as e:
                return Response({'code': 500, "message": '获取热线数据失败', "error": str(e)})
            ser = WarnSerializer(instance=warn_obj, many=False)
            return Response({"code": 200, "data": ser.data})
        else:
            return Response(login_status)


class WarnViewUser(APIView):
    def get(self, request):   # 用户
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            try:
                warn_obj = Warn.objects.last()
            except Exception as e:
                return Response({'code': 500, "message": '获取热线数据失败', "error": str(e)})
            ser = WarnSerializer(instance=warn_obj, many=False)
            return Response({"code": 200, "data": ser.data})
        else:
            return Response(login_status)


class HotlineView(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            ser = HotlineSerializer(data=request.data)
            if ser.is_valid():
                try:
                    Hotline.objects.create(**ser.validated_data)
                except Exception as e:
                    return Response({'code': 500, "message": '增加热线失败', "error": str(e)})
                return Response({'code': 200, "message": '上传成功'})
            else:
                return Response({'code': 400, "message": '数据格式错误', "data": ser.errors})
        else:
            return Response(login_status)

    def get(self, request):
        token = request.headers.get('Authorization')
        login_status_manager = is_login_manager(token)
        if login_status_manager['code'] == 200:
            try:
                hotline_obj = Hotline.objects.all()
            except Exception as e:
                return Response({'code': 500, "message": '获取热线数据失败', "error": str(e)})
            if hotline_obj:
                ser = HotlineSerializer(instance=hotline_obj, many=True)
                return Response({"code": 200, "data": ser.data})
            else:
                return Response({"code": 404, "message": '未查询到'})
        else:
            return Response(login_status_manager)


class HotlineUser(APIView):
    def get(self, request):  # 这里的get为用户查询
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            try:
                params = Hotline.objects.all()
            except Exception as e:
                return Response({'code': 500, "message": '获取热线失败', "error": str(e)})
            if params:  # 改了下,现在是如果params为空的话，会返回状态码400(验证过了)
                ser = HotlineSerializer(instance=params, many=True)
                return Response({'code': 200, 'data': ser.data, 'message': '获取所有热线信息'})
            else:
                return Response({'code': 404, 'message': '无热线信息'})
        else:
            return Response(login_status)


class HotlineDetailView(APIView):
    def put(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            ser = HotlineSerializer(data=request.data)
            if ser.is_valid():
                try:
                    Hotline.objects.filter(pk=pk).update(**ser.validated_data)
                except Exception as e:
                    return Response({'code': 500, "message": '修改热线失败', "error": str(e)})
                return Response({'code': 200, "message": '修改成功'})
            else:
                return Response({'code': 400, "message": '数据格式错误', "data": ser.errors})
        else:
            return Response(login_status)

    def delete(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                Hotline.objects.filter(pk=pk).delete()
                return Response({'code': 200, "message": '删除成功'})
            except Exception as e:
                return Response({'code': 404, "message": '删除失败', "error": str(e)})
        else:
            return Response(login_status)


class CoverView(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            cover_file = request.FILES.get('cover_file')
            if not cover_file:
                return JsonResponse({'code': 400, "message": '封面上传失败'})
            else:
                try:
                    Cover.objects.create(cover_file=cover_file)
                    return Response({'code': 200, "message": '上传成功'})
                except Exception as e:
                    return Response({'code': 500, "message": '上传失败', "error": str(e)})
        else:
            return Response(login_status)

    def get(self, request):   # 只有管理员
        token = request.headers.get('Authorization')
        login_status_manager = is_login_manager(token)
        if login_status_manager['code'] == 200:
            obj = Cover.objects.all()
            if obj:
                ser = CoverSerializer(instance=obj, many=True)
                return Response({'code': 200, 'data': ser.data, 'message': '获取封面成功'})
            else:
                return Response({"code": 404 , "message": '未找到相关图片'})
        else:
            return Response(login_status_manager)


class CoverDetailView(APIView):
    def delete(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                Cover.objects.filter(pk=pk).delete()
                return Response({'code': 200, "message": '删除成功'})
            except Exception as e:
                return Response({'code': 500, "message": '删除失败', "error": str(e)})
        else:
            return Response(login_status)

    def put(self, request, pk):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            cover_file = request.FILES.get('cover_file')
            if not cover_file:
                return JsonResponse({'code': 400, "message": '封面修改失败'})
            else:
                try:
                    Cover.objects.filter(pk=pk).update(cover_file=cover_file)
                    return Response({'code': 200, "message": '修改成功'})
                except Exception as e:
                    return Response({'code': 500, "message": '封面更新失败', "error": str(e)})
        else:
            return Response(login_status)


class FrequencyView(APIView):   # manager的函数
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                obj = User.objects.all().values('user_freq')
                total_sum = sum(item['user_freq'] for item in obj)  # 可以实现把User中所有对象的user_freq取出，并加和的功能
                return Response({'code': 200, 'data': total_sum, 'message': '获取总访问量成功'})
            except Exception as e:
                return Response({'code': 500, "message": '获取总量失败', "error": str(e)})
        else:
            return Response(login_status)


class BackgroundView(APIView):
    def post(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)

        if login_status['code'] == 200:
            back_file = request.FILES.get('back_file')
            if not back_file:
                return JsonResponse({'code': 400, "message": '封面上传失败'})
            else:
                try:
                    # 删除所有现有的图片记录
                    Background.objects.all().delete()

                    # 创建新的图片记录
                    Background.objects.create(back_file=back_file)

                    return Response({'code': 200, "message": '上传成功'})
                except Exception as e:
                    return Response({'code': 500, "message": '上传失败', "error": str(e)})
        else:
            return Response(login_status)

    def get(self, request):
        obj = Background.objects.all()
        if obj:
            ser = BackSerializer(instance=obj, many=True)
            return Response({'code': 200, 'data': ser.data, 'message': '获取封面成功'})
        else:
            return Response({'code': 404, 'message': '未找到相关图片'})


from datetime import timedelta
import pytz

flag = 5


class GetExcelNew(APIView):
    def post(self, request):
        global flag
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                json_data = json.loads(request.body)
                time1 = json_data.get('start_time')
                time2 = json_data.get('finish_time')
            except Exception as e:
                response_content = {
                    'message': '时间格式出错',
                    'errors': str(e)
                }
                return JsonResponse(response_content, status=201)

            # 解析 request 中的 naive 时间
            try:
                naive_time1 = dt.strptime(time1, '%Y-%m-%d')
                naive_time2 = dt.strptime(time2, '%Y-%m-%d')
            except Exception as e:
                response_content = {
                    'message': '时间格式出错',
                    'errors': str(e)
                }
                return JsonResponse(response_content, status=201)

            # 将 naive 时间本地化到东八区
            try:
                tz = pytz.timezone('Asia/Shanghai')
                time1_with_tz = tz.localize(naive_time1)
                time2_with_tz = tz.localize(naive_time2)
                # 仅用于查询
                start_time = time1_with_tz.strftime('%Y-%m-%d-%H')
                finish_time = time2_with_tz.strftime('%Y-%m-%d-%H')
            except Exception as e:
                response_content = {
                    'message': '时间格式出错',
                    'errors': str(e)
                }
                return JsonResponse(response_content, status=201)

            if start_time == finish_time:
                try:
                    obj1 = Complaint.objects.filter(comp_sub_time__date=time1_with_tz.date())
                    obj2 = Suggestion.objects.filter(sugg_sub_time__date=time1_with_tz.date())
                    if obj1 and obj2:
                        pass
                    elif not obj1 and not obj2:
                        response_content = {
                            'message': '未找到时间范围内的表单',
                        }
                        return JsonResponse(response_content, status=201)
                    elif not obj1 and obj2:
                        flag = 1  # 没投诉有建议
                    elif obj1 and not obj2:
                        flag = 2  # 有投诉没建议
                except Exception as e:
                    response_content = {
                        'message': '时间格式出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)
            else:
                try:
                    obj1 = Complaint.objects.filter(comp_sub_time__range=(time1_with_tz, time2_with_tz))
                    obj2 = Suggestion.objects.filter(sugg_sub_time__range=(time1_with_tz, time2_with_tz))
                    if obj1 and obj2:
                        flag = 0
                    elif not obj1 and not obj2:
                        response_content = {
                            'message': '未找到时间范围内的表单',
                        }
                        return JsonResponse(response_content, status=201)
                    elif not obj1 and obj2:
                        flag = 1  # 没投诉有建议
                    elif obj1 and not obj2:
                        flag = 2  # 有投诉没建议
                except Exception as e:
                    response_content = {
                        'message': '时间格式出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)
            if flag == 2:
                try:
                    obj1_list = list(obj1.values(
                        'comp_name', 'comp_title', 'comp_user_tele', 'comp_text', 'comp_site',
                        'comp_sub_time', 'comp_status', 'comp_staff_name', 'comp_content',
                        'comp_way', 'comp_handle_time', 'comp_staff_tele', 'comp_treat', 'comp_feedback',
                        'comp_summary'
                    ))
                    obj2_list = [{' ': ' '}]
                    df = pd.DataFrame(obj1_list)
                    df2 = pd.DataFrame(obj2_list)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                try:
                    status_mapping = {
                        False: '未处理',
                        True: '已处理'
                    }
                    # 应用状态映射
                    df['comp_status'] = df['comp_status'].replace(status_mapping)
                    treat_mapping = {
                        0: '不需要回访',
                        1: '暂未回访',
                        2: '已回访'
                    }
                    df['comp_treat'] = df['comp_treat'].replace(treat_mapping)
                    feedback_mapping = {
                        0: '',
                        1: '非常满意',
                        2: '满意',
                        3: '基本满意',
                        4: '一般',
                        5: '不满意',
                    }
                    df['comp_feedback'] = df['comp_feedback'].replace(feedback_mapping)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                def format_date(datetime_obj):
                    # 确保 datetime_obj 是带时区信息的 datetime 对象
                    try:
                        # 使用 pandas 的 to_datetime 保留时区信息
                        datetime_with_tz = pd.to_datetime(datetime_obj, utc=True).tz_convert('Asia/Shanghai')
                    except Exception as e11:
                        response_content22 = {
                            'message': '下载excel出错',
                            'errors': str(e11)
                        }
                        return JsonResponse(response_content22, status=201)
                    # 按指定格式输出时间，包括时区信息
                    return datetime_with_tz.strftime('%Y年%m月%d日%H时')

                try:
                    df['comp_sub_time'] = df['comp_sub_time'].apply(format_date)
                    df['comp_handle_time'] = df['comp_handle_time'].apply(format_date)
                    df.columns = ['投诉人姓名', '投诉标题', '投诉人电话', '投诉内容', '投诉地点', '投诉时间', '处理状态',
                                  '处理人姓名', '处理内容', '处理方式', '处理时间', '处理人电话', '是否需要回访',
                                  '居民反馈评价(五个等级依次为：不满意、一般满意、较为满意、满意、非常满意)', '回访总结']
                    df2.columns = ['建议表为空']
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                # 设置工作文件夹路径
                work_folder = '/room/docker_media/files/'

                # 确保工作文件夹存在
                try:
                    if not os.path.exists(work_folder):
                        print("路径")
                        os.makedirs(work_folder)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                # 设置Excel文件名
                try:
                    print("创建路径")
                    timestamp = dt.now().strftime('%Y%m%d_%H%M%S')
                    excel_filename = f'投诉记录_{timestamp}.xlsx'
                    excel_filepath = os.path.join(work_folder, excel_filename)
                    # 将DataFrame保存为Excel文件
                    with pd.ExcelWriter(excel_filepath) as writer:
                        df.to_excel(writer, sheet_name='居民诉求', index=False)
                        df2.to_excel(writer, sheet_name='居民建议', index=False)

                    print(f"Excel file generated at: {excel_filepath}")
                    # 确保文件确实存在
                    if not os.path.isfile(excel_filepath):
                        raise FileNotFoundError(f"File not found at path: {excel_filepath}")
                    # 读取文件并提供下载
                    file = open(excel_filepath, 'rb')
                    response = FileResponse(file)
                    # 使用生成的Excel文件名作为返回的文件名
                    response['Content-Disposition'] = f'attachment; filename="{excel_filename}"'
                    return response
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)
            elif flag == 1:
                try:
                    obj1_list = [{' ': ' '}]
                    obj2_list = list(obj2.values(
                        'sugg_name', 'sugg_title', 'sugg_user_tele', 'sugg_text', 'sugg_site',
                        'sugg_sub_time', 'sugg_status', 'sugg_staff_name', 'sugg_content',
                        'sugg_way', 'sugg_handle_time', 'sugg_staff_tele', 'sugg_treat', 'sugg_feedback',
                        'sugg_summary'
                    ))
                    df = pd.DataFrame(obj1_list)
                    df2 = pd.DataFrame(obj2_list)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                try:
                    status_mapping = {
                        False: '未处理',
                        True: '已处理'
                    }
                    # 应用状态映射
                    df2['sugg_status'] = df2['sugg_status'].replace(status_mapping)
                    treat_mapping = {
                        0: '不需要回访',
                        1: '暂未回访',
                        2: '已回访'
                    }
                    df2['sugg_treat'] = df2['sugg_treat'].replace(treat_mapping)
                    feedback_mapping = {
                        0: '',
                        1: '非常满意',
                        2: '满意',
                        3: '基本满意',
                        4: '一般',
                        5: '不满意',
                    }
                    df2['comp_feedback'] = df2['comp_feedback'].replace(feedback_mapping)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                def format_date(datetime_obj):
                    # 确保 datetime_obj 是带时区信息的 datetime 对象
                    try:
                        # 使用 pandas 的 to_datetime 保留时区信息
                        datetime_with_tz = pd.to_datetime(datetime_obj, utc=True).tz_convert('Asia/Shanghai')
                    except Exception as e1:
                        response_content11 = {
                            'message': '下载excel出错',
                            'errors': str(e1)
                        }
                        return JsonResponse(response_content11, status=201)
                    # 按指定格式输出时间，包括时区信息
                    return datetime_with_tz.strftime('%Y年%m月%d日%H时')

                try:
                    df2['sugg_sub_time'] = df2['sugg_sub_time'].apply(format_date)
                    df2['sugg_handle_time'] = df2['sugg_handle_time'].apply(format_date)
                    df2.columns = ['建议人姓名', '建议标题', '建议人电话', '建议内容', '建议地点', '建议时间', '处理状态',
                                  '处理人姓名',
                                    '处理内容', '处理方式', '处理时间', '处理人电话', '是否需要回访',
                                  '居民反馈评价(五个等级依次为：不满意、一般满意、较为满意、满意、非常满意)', '回访总结']
                    df.columns = ['投诉表为空']
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                # 设置工作文件夹路径
                work_folder = '/room/docker_media/files/'

                # 确保工作文件夹存在
                try:
                    if not os.path.exists(work_folder):
                        print("路径")
                        os.makedirs(work_folder)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                # 设置Excel文件名
                try:
                    print("创建路径")
                    timestamp = dt.now().strftime('%Y%m%d_%H%M%S')
                    excel_filename = f'建议记录_{timestamp}.xlsx'
                    excel_filepath = os.path.join(work_folder, excel_filename)
                    # 将DataFrame保存为Excel文件
                    with pd.ExcelWriter(excel_filepath) as writer:
                        df2.to_excel(writer, sheet_name='居民建议', index=False)
                        df.to_excel(writer, sheet_name='居民投诉', index=False)
                    # 确保文件确实存在
                    if not os.path.isfile(excel_filepath):
                        raise FileNotFoundError(f"File not found at path: {excel_filepath}")
                    # 读取文件并提供下载
                    file = open(excel_filepath, 'rb')
                    response = FileResponse(file)
                    # 使用生成的Excel文件名作为返回的文件名
                    response['Content-Disposition'] = f'attachment; filename="{excel_filename}"'
                    return response
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)
            elif flag == 0:
                try:
                    obj1_list = list(obj1.values(
                        'comp_name', 'comp_title', 'comp_user_tele', 'comp_text', 'comp_site',
                        'comp_sub_time', 'comp_status', 'comp_staff_name', 'comp_content',
                        'comp_way', 'comp_handle_time', 'comp_staff_tele', 'comp_treat', 'comp_feedback',
                        'comp_summary'
                    ))
                    obj2_list = list(obj2.values(
                        'sugg_name', 'sugg_title', 'sugg_user_tele', 'sugg_text', 'sugg_site',
                        'sugg_sub_time', 'sugg_status', 'sugg_staff_name', 'sugg_content',
                        'sugg_way', 'sugg_handle_time', 'sugg_staff_tele', 'sugg_treat', 'sugg_feedback',
                        'sugg_summary'
                    ))
                    df = pd.DataFrame(obj1_list)
                    df2 = pd.DataFrame(obj2_list)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                try:
                    status_mapping = {
                        False: '未处理',
                        True: '已处理'
                    }
                    # 应用状态映射
                    df['comp_status'] = df['comp_status'].replace(status_mapping)
                    df2['sugg_status'] = df2['sugg_status'].replace(status_mapping)
                    treat_mapping = {
                        0: '不需要回访',
                        1: '暂未回访',
                        2: '已回访'
                    }
                    df['comp_treat'] = df['comp_treat'].replace(treat_mapping)
                    df2['sugg_treat'] = df2['sugg_treat'].replace(treat_mapping)
                    feedback_mapping = {
                        0: '',
                        1: '非常满意',
                        2: '满意',
                        3: '基本满意',
                        4: '一般',
                        5: '不满意',
                    }
                    df['comp_feedback'] = df['comp_feedback'].replace(feedback_mapping)
                    df2['sugg_feedback'] = df2['sugg_feedback'].replace(feedback_mapping)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                def format_date(datetime_obj):
                    # 确保 datetime_obj 是带时区信息的 datetime 对象
                    try:
                        # 使用 pandas 的 to_datetime 保留时区信息
                        datetime_with_tz = pd.to_datetime(datetime_obj, utc=True).tz_convert('Asia/Shanghai')
                    except Exception as e1:
                        response_content1 = {
                            'message': '下载excel出错',
                            'errors': str(e1)
                        }
                        return JsonResponse(response_content1, status=201)
                    # 按指定格式输出时间，包括时区信息
                    return datetime_with_tz.strftime('%Y年%m月%d日%H时')

                try:
                    df['comp_sub_time'] = df['comp_sub_time'].apply(format_date)
                    df['comp_handle_time'] = df['comp_handle_time'].apply(format_date)
                    df.columns = ['投诉人姓名', '投诉标题', '投诉人电话', '投诉内容', '投诉地点', '投诉时间',
                                  '处理状态',
                                  '处理人姓名', '处理内容', '处理方式', '处理时间', '处理人电话', '是否需要回访',
                                  '居民反馈评价(五个等级依次为：不满意、一般满意、较为满意、满意、非常满意)', '回访总结']
                    df2['sugg_sub_time'] = df2['sugg_sub_time'].apply(format_date)
                    df2['sugg_handle_time'] = df2['sugg_handle_time'].apply(format_date)
                    df2.columns = ['建议人姓名', '建议标题', '建议人电话', '建议内容', '建议地点', '建议时间',
                                   '处理状态',
                                   '处理人姓名', '处理内容', '处理方式', '处理时间', '处理人电话', '是否需要回访',
                                   '居民反馈评价(五个等级依次为：不满意、一般满意、较为满意、满意、非常满意)', '回访总结']
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                # 设置工作文件夹路径
                work_folder = '/room/docker_media/files/'

                # 确保工作文件夹存在
                try:
                    if not os.path.exists(work_folder):
                        print("路径")
                        os.makedirs(work_folder)
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)

                # 设置Excel文件名
                try:
                    timestamp = dt.now().strftime('%Y%m%d_%H%M%S')
                    excel_filename = f'建议投诉记录_{timestamp}.xlsx'
                    excel_filepath = os.path.join(work_folder, excel_filename)
                    # 将DataFrame保存为Excel文件
                    with pd.ExcelWriter(excel_filepath) as writer:
                        df.to_excel(writer, sheet_name='居民诉求', index=False)
                        df2.to_excel(writer, sheet_name='居民建议', index=False)

                    print(f"Excel file generated at: {excel_filepath}")
                    # 确保文件确实存在
                    if not os.path.isfile(excel_filepath):
                        raise FileNotFoundError(f"File not found at path: {excel_filepath}")
                    # 读取文件并提供下载
                    file = open(excel_filepath, 'rb')
                    response = FileResponse(file)
                    # 使用生成的Excel文件名作为返回的文件名
                    response['Content-Disposition'] = f'attachment; filename="{excel_filename}"'
                    return response
                except Exception as e:
                    response_content = {
                        'message': '下载excel出错',
                        'errors': str(e)
                    }
                    return JsonResponse(response_content, status=201)
            else:
                response_content = {
                    'message': "选定时间内无投诉和建议表"
                }
                return JsonResponse(response_content, status=201)
        else:
            return JsonResponse(login_status, status=201)


class CountSumView(APIView):
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_manager(token)
        if login_status['code'] == 200:
            try:
                obj1 = Suggestion.objects.filter(sugg_status=True).all().count()
                obj2 = Suggestion.objects.filter(sugg_status=False).all().count()
                obj3 = Complaint.objects.filter(comp_status=True).all().count()
                obj4 = Complaint.objects.filter(comp_status=False).all().count()
            except Exception as e:
                return Response({'code': 500, "message": '获取总量失败', "error": str(e)})
            data = {
                'sugg_done': obj1,
                'sugg_todo': obj2,
                'comp_done': obj3,
                'comp_todo': obj4
            }
            return Response({'code': 200, 'data': data, 'message': "成功获取"})
        else:
            return Response(login_status)


# 假设response.text是从网页获取的HTML内容
limit_url = "https://jtgl.beijing.gov.cn/"
limit_headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"}

def getXHNumber(tDate: datetime.datetime, sDate: datetime.datetime):
    nDayNum = tDate.weekday() + 1
    if nDayNum > 5:
        return nDayNum
    nDiff = (tDate - sDate).days / (7 * 13)
    nDiff = math.floor(nDiff) % 5
    nDayNum = 5 - nDiff + nDayNum
    if nDayNum > 5:
        nDayNum -= 5
    return nDayNum


def xianxing():
    # 获取网页信息
    try:
        response = requests.get(limit_url, headers=limit_headers)
        response.encoding = 'utf-8'
        soup = BeautifulSoup(response.text, 'html.parser')
        scripts = soup.find_all('script', attrs={'type': 'text/javascript'})
        # 用于存储Holiday数组的字符串
        holiday_script = ""
        # 查找包含Holiday数组定义的<script>标签
        for script in scripts:
            if script.string and "var Holiday=new Array" in script.string:
                holiday_script = script.string
                break
        # 使用正则表达式从JavaScript代码中提取日期
        Holiday = re.findall(r'"(\d{4}-\d{1,2}-\d{1,2})"', holiday_script)
    except Exception as e:
        return Response({'code': 500, "message": '获取限行信息出错', "error": str(e)})

    sStartDate = '2014-04-14'  # 开始星期，周一的日期
    x = [None, '5和0', '1和6', '2和7', '3和8', '4和9', '-', '-']

    vStartDate = datetime.datetime.strptime(sStartDate, "%Y-%m-%d")
    vToday = datetime.datetime.now()  # 客户端当天时间

    nDayNum1 = getXHNumber(vToday, vStartDate)  # 限行尾号数组值
    vToday += datetime.timedelta(days=1)
    nDayNum2 = getXHNumber(vToday, vStartDate)

    # 判断今天和明天是否为节假日
    for holiday in Holiday:
        tddate = datetime.datetime.strptime(holiday, "%Y-%m-%d")
        if vToday.strftime("%Y-%m-%d") == tddate.strftime("%Y-%m-%d"):
            nDayNum1 = 6
        if (vToday + datetime.timedelta(days=1)).strftime("%Y-%m-%d") == tddate.strftime("%Y-%m-%d"):
            nDayNum2 = 6

    return x[nDayNum1], x[nDayNum2]


class LimitFinal(APIView):  # 用户查询限行信息
    def get(self, request):
        token = request.headers.get('Authorization')
        login_status = is_login_user(token)
        if login_status['code'] == 200:
            try:
                today_limit, tomorrow_limit = xianxing()
                today_numbers = re.findall(r'\d+', today_limit)
                tomorrow_numbers = re.findall(r'\d+', tomorrow_limit)
                today_limit1, today_limit2 = today_numbers
                tomorrow_limit1, tomorrow_limit2 = tomorrow_numbers
            except Exception as e:
                return Response({'code': 500, "message": 'post中获取限行信息出错', "error": str(e)})
            #  构建返回体
            limit_result = {
                "today_limit1": today_limit1,
                "today_limit2": today_limit2,
                "tomorrow_limit1": tomorrow_limit1,
                "tomorrow_limit2": tomorrow_limit2
            }
            return Response({'code': 200, 'data': limit_result, 'message': "成功获取限行数据"})
        else:
            return Response(login_status)
